package part9.interpreter;

import token.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class Lexer {
    private final String text;
    private int pos;
    private Character currentChar;

    static public Map<String, Token> reservedKeywords = new HashMap<>();

    public Lexer(String text) {
        this.text = text;
        this.pos = 0;
        this.currentChar = this.text.charAt(pos);

        reservedKeywords.put("BEGIN", new TK_BEGIN());
        reservedKeywords.put("END", new TK_END());
    }

    private void error() throws Exception {
        throw new Exception("Invalid character");
    }

    private void advance(){
        pos++;
        if (pos>text.length()-1){
            this.currentChar = null;
        }
        else {
            this.currentChar = text.charAt(pos);
        }
    }

    // 添加的函数
    private Character peek() {
        int peekPos = pos+1;
        if (peekPos > text.length() - 1){
            return null;
        }
        else {
            return text.charAt(peekPos);
        }
    }

    private boolean isSpace(char c){
        return c == ' ' || c=='\t' || c=='\n';
    }

    private void skipWhitespace(){
        while (this.currentChar!=null && isSpace(this.currentChar)){
            this.advance();
        }
    }

    private int integer(){
        StringBuilder sb = new StringBuilder();
        while (currentChar!=null && Character.isDigit(currentChar)){
            sb.append(currentChar);
            this.advance();
        }
        return Integer.parseInt(sb.toString());
    }

    private Token _id(){
        StringBuilder sb = new StringBuilder();
        while (currentChar != null && Character.isLetterOrDigit(currentChar)){
            sb.append(currentChar);
            advance();
        }
        return reservedKeywords.getOrDefault(sb.toString(), new TK_ID(sb.toString()));
    }

    public Token getNextToken() throws Exception {
        while (currentChar != null){
            if (isSpace(currentChar)){
                skipWhitespace();
                continue;
            }
            if (Character.isLetter(currentChar)){
                return this._id();
            }
            if (Character.isDigit(currentChar)){
                return new TK_Integer(this.integer());
            }
            if (currentChar == ':' && Objects.requireNonNull(this.peek()).equals('=')){
                advance();
                advance();
                return new TK_Assign();
            }
            Token res = null;
            switch (currentChar) {
                case ';':
                    res = new TK_Semi();
                    break;
                case '+':
                    res = new TK_Plus();
                    break;
                case '-':
                    res = new TK_Minus();
                    break;
                case '*':
                    res = new TK_Mul();
                    break;
                case '/':
                    res = new TK_Div();
                    break;
                case '(':
                    res = new TK_Lparen();
                    break;
                case ')':
                    res = new TK_Rparen();
                    break;
                case '.':
                    res = new TK_Dot();
                    break;
                default:
                    error();
                    break;
            }
            advance();
            return res;
        }
        return new TK_EOF();
    }
}
